<?php

namespace App\Console\Commands;

use App\Enums\DivideStatus;
use App\Enums\PaymentStatus;
use App\Models\AgentConfig;
use App\Models\Order;
use App\Models\OrderPayment;
use App\Models\Store;
use App\Services\YeepayService;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;

class OrderDivideCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'order:divide {--retry}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '订单分账';

    /**
     * Create a new command instance.
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle(YeepayService $yeepayService)
    {
        // 查询所有支付完成的订单
        /** @var OrderPayment[] $payments */
        $payments = OrderPayment::query()
            ->with(['order'])
            ->where('pay_status', PaymentStatus::FINISHED)
            ->where('pay_time', '<=', now()->subMinutes(5))
            ->when($this->option('retry'), function ($q) {
                return $q->where('divide_status', DivideStatus::FAILED);
            })
            ->when(!$this->option('retry'), function ($q) {
                return $q->where('divide_status', DivideStatus::INIT);
            })
            ->orderByDesc('id')
            ->limit(50)
            ->get();

        $msg = '待分账订单数量: ' . count($payments);
        \Log::info($msg);
        foreach ($payments as $payment) {
            $order = $payment->order;
            if (!$order) {
                continue;
            }

            try {
                $orderInfo = $yeepayService->queryOrder($payment->out_order_no);
            } catch (\Exception $e) {
                $payment->divide_status = DivideStatus::FAILED;
                $payment->divide_fail_reason = 'yeepay order query failed';
                $payment->save();

                continue;
            }
            // 查询手续费相关配置
            $agentConfigs = AgentConfig::query()
                ->where('agent_id', $order->agent_id)
                ->whereIn('config_key', [
                    AgentConfig::PAY_MERCHANT_NO,               // 代理子商户号:用于分账
                    AgentConfig::PAY_SERVICE_FEE_RATE,          // 平台发行订单手续费率
                    AgentConfig::PAY_RESALE_SERVICE_FEE_RATE,   // 平台转售订单手续费率
                    AgentConfig::PAY_RESALE_AGENT_FEE_RATE,     // 代理转售订单手续费率
                ])->get()->mapWithKeys(function (AgentConfig $config) {
                    return [$config->config_key => $config->config_value];
                });
            $divideDetail = [];
            $merchantFee = toFen(Arr::get($orderInfo, 'merchantFee')); // 支付手续费
            $orderAmount = $payment->pay_amount;
            $receiveAmount = $orderAmount - $merchantFee;
            $agentMerchantNo = Arr::get($agentConfigs, AgentConfig::PAY_MERCHANT_NO);
            // 平台交易手续费
            if ($order->is_resale) {
                $serviceFeeRate = Arr::get($agentConfigs, AgentConfig::PAY_RESALE_SERVICE_FEE_RATE, 0);
            } else {
                $serviceFeeRate = Arr::get($agentConfigs, AgentConfig::PAY_SERVICE_FEE_RATE, 0);
            }
            $serviceFee = floor($orderAmount * $serviceFeeRate / 100) - $merchantFee + 100; //易宝针对NFT交易每笔加收1元手续费，由发行方或转售用户承担
            $serviceFee = min($serviceFee, $receiveAmount);
            if ($serviceFee < 0) {
                $payment->divide_status = DivideStatus::FAILED;
                $payment->divide_fail_reason = '平台手续费少于支付渠道手续费，无法分账';
                $payment->save();

                break;
            }

            if ($serviceFee > 0) {
                $divideDetail[] = [
                    'ledgerNo' => config('services.yeepay.platform_merchant_no'),
                    'amount' => toYuan($serviceFee),
                    'divideDetailDesc' => sprintf(
                        '平台交易手续费-支付通道手续费+1: %s x %s - %s + 1 = %s',
                        toYuan($orderAmount),
                        $serviceFeeRate / 100,
                        toYuan($merchantFee),
                        toYuan($serviceFee)
                    ),
                ];
            }
            if ($order->is_resale) {
                $storeFee = 0;
                // 代理转售手续费
                $agentFeeRate = Arr::get($agentConfigs, AgentConfig::PAY_RESALE_AGENT_FEE_RATE, 0);
                $agentFee = floor($orderAmount * $agentFeeRate / 100);
                if ($agentFee > 0) {
                    $divideDetail[] = [
                        'ledgerNo' => $agentMerchantNo,
                        'amount' => toYuan($agentFee),
                        'divideDetailDesc' => sprintf(
                            '代理收取转售手续费: %s x %s = %s',
                            toYuan($orderAmount),
                            $agentFeeRate / 100,
                            toYuan($agentFee)
                        ),
                    ];
                }
                $userFee = $receiveAmount - $serviceFee - $agentFee;
                if ($userFee > 0) {
                    $divideDetail[] = [
                        'ledgerNo' => $order->product->resale_user->auth->merchant_no,
                        'amount' => toYuan($userFee),
                        'divideDetailDesc' => sprintf(
                            '用户收入=实际入账金额-平台手续费-代理手续费: %s - %s - %s = %s ',
                            toYuan($receiveAmount),
                            toYuan($serviceFee),
                            toYuan($agentFee),
                            toYuan($userFee)
                        ),
                    ];
                }
            } else {
                $userFee = $storeFee = 0;
                /** @var Order $order */
                $order = Order::query()->find($payment->order_id);
                if ($order->product->store_id) {
                    /** @var Store $store */
                    $store = Store::query()->find($order->product->store_id);
                    if ($store && $store->divide_account) {
                        $agentServiceFeeRate = $store->agent_service_fee_rate;
                    }
                }

                if (!empty($agentServiceFeeRate)) {
                    $agentFee = floor($orderAmount * $agentServiceFeeRate / 100);
                    $storeFee = $receiveAmount - $serviceFee - $agentFee;
                } else {
                    $agentFee = $receiveAmount - $serviceFee;
                }

                if ($agentFee > 0) {
                    $divideDetail[] = [
                        'ledgerNo' => $agentMerchantNo,
                        'amount' => toYuan($agentFee),
                        'divideDetailDesc' => sprintf(
                            '代理商收入=实际入账金额-平台手续费: %s - %s = %s',
                            toYuan($receiveAmount),
                            toYuan($serviceFee),
                            toYuan($agentFee)
                        ),
                    ];
                }
                if ($storeFee > 0 && !empty($store)) {
                    $divideDetail[] = [
                        'ledgerNo' => $store->divide_account,
                        'amount' => toYuan($storeFee),
                        'divideDetailDesc' => sprintf(
                            '门店收入=实际入账金额-平台手续费-代理收入: %s - %s - %s= %s',
                            toYuan($receiveAmount),
                            toYuan($serviceFee),
                            toYuan($agentFee),
                            toYuan($storeFee)
                        ),
                    ];
                }
            }

            try {
                $payment->receive_amount = $orderAmount - $merchantFee;
                $payment->platform_receive_amount = $serviceFee;
                $payment->agent_receive_amount = $agentFee;
                $payment->user_receive_amount = $userFee;
                $payment->store_receive_amount = $storeFee;
                if (!empty($divideDetail)) {
                    $orderNo = Arr::get($orderInfo, 'uniqueOrderNo');
                    $divideResult = $yeepayService->divideApply($payment->out_order_no, $orderNo, $divideDetail);
                    $divideStatus = Arr::get($divideResult, 'status');
                    if ('SUCCESS' === $divideStatus) {
                        $payment->divide_status = DivideStatus::DIVIDED;
                    }
                    if ('PROCESSING' === $divideStatus) {
                        $payment->divide_status = DivideStatus::DIVIDING;
                    }
                } else {
                    $payment->divide_status = DivideStatus::DIVIDED;
                }
            } catch (\Exception $e) {
                $payment->divide_status = DivideStatus::FAILED;
                $payment->divide_fail_reason = $e->getMessage();
            } finally {
                $payment->save();
            }
        }

        return 0;
    }
}
